package com.distribute.framework.plugin;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import com.distribute.framework.config.DatabaseNames;
import com.distribute.framework.core.lang.caption;
import com.distribute.framework.core.web.helper.Utils;
import java.util.*;

/**
 * 全局触发器
 * @author 飞啊飘啊
 */
public class Trigger{
	
	public static enum Type{SAVE,UPDATE,DELETE,UPDATENOTNULL,UPDATEBY,DELETEBY}
	public final static Type SAVE = Type.SAVE;
	public final static Type UPDATE = Type.UPDATE;
	public final static Type DELETE = Type.DELETE;
	public final static Type UPDATE_NOTNULL = Type.UPDATENOTNULL;
	public final static Type UPDATE_BY = Type.UPDATEBY;
	public final static Type DELETE_BY = Type.DELETEBY;
	
	
	public static enum Index{AFTER,BEFOR}
	public final static Index AFTER = Index.AFTER;
	public final static Index BEFOR = Index.BEFOR;
	
	
	/**
	 * 对象修改事件
	 * [ClassName][after|before][save|update|delete],object|id|params
	 * @param <T>
	 * @param cls 模型类
	 * @param index 修改前或后
	 * @param type 类型：添加，修改，删除
	 * @param params 查询参数
	 * @param sets 修改对象
	 * @return
	 */
	public static <T> T on(final Class cls,final Index index,final Type type,final T t){	
		Map<String,String> modifys = Utils.getLocal("modifys");
		if(modifys!=null)modifys.put(cls.getSimpleName(), type.name());
		if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+index.name()+"."+type.name())!=null){
			Map map = Utils.eval(Utils.json(t));
			for(Object key:map.keySet()){
				if(map.get(key)==null)
					map.remove(key);
			}
			Notify.sendTextMessage(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+index.name()+"."+type.name(),Utils.json(map), false);
		}
		return t;
	}
	
	public static <T> T on(final Class cls,final String type,final T t){
		Map<String,String> modifys = Utils.getLocal("modifys");
		if(modifys!=null)modifys.put(cls.getSimpleName(), type);
		if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+type)!=null){
			Map map = Utils.eval(Utils.json(t));
			for(Object key:map.keySet()){
				if(map.get(key)==null)
					map.remove(key);
			}
			Notify.sendTextMessage(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+type,Utils.json(map), false);
		}
		return t;
	}
	
	
	
	public static boolean have(final Class cls, Map params) {
		for(Object key:params.keySet()){
			if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key)!=null){
				return true;
			}
			if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key+"."+Utils.md5(""+params.get(key)))!=null){
				return true;
			}
		}
		return false;
	}

	public static <T> void on(final Class cls, T a,T b) {
		Map<String, String> params = getUpdates(a,b);
		String json = null;
		for(Object key:params.keySet()){
			if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key)!=null){
				if(json==null)json = Utils.json(Utils.add("a", a).add("b", b));
				Notify.sendTextMessage(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key,json,false);
			}
			if(Notify.getSubscribe(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key+"."+Utils.md5(params.get(key)))!=null){
				if(json==null)json = Utils.json(Utils.add("a", a).add("b", b));
				Notify.sendTextMessage(DatabaseNames.get(cls, "broker"),cls.getSimpleName()+"."+key+"."+Utils.md5(params.get(key)),json, false);
			}
		}
	}
	
	/**
	 * 获取对象被修改的字段列表
	 * @param oldObject
	 * @param newObject
	 * @return
	 */
	public static Map<String,String> getUpdates(Object oldObject,Object newObject) {
		Map<String,String> updates = new HashMap();
		if(newObject==null)return updates;
		Field[] fields = newObject.getClass().getDeclaredFields();
		for(Field field:fields){
			field.setAccessible(true);
			if(field.getAnnotation(caption.class)==null)
				continue;
			String fieldName = field.getName();
			try{
				Object oldValue = field.get(oldObject);
				Object newValue = field.get(newObject);
				if(newValue!=null && !Utils.equals(""+newValue, ""+oldValue)){
					updates.put(fieldName, ""+newValue);
				}
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
		return updates;
	}
	
	
}